<script setup lang="ts">
import { useResizeObserver } from "@vueuse/core";
import {
  computed,
  ref,
  type Ref,
  watch,
  onMounted,
  onBeforeUnmount,
  onUnmounted
} from "vue";
import { useAppStoreHook } from "@/store/modules/app";
import {
  delay,
  type EchartOptions,
  useDark,
  useECharts,
  UtilsEChartsOption
} from "@pureadmin/utils";
import {
  defaultChartOption,
  defaultSetting
} from "@/views/monitor/components/DefaultConfig";
import { hisdataChartOption } from "@/views/monitor/components/hisdataConfig";

import InstanceDataSetting from "./InstanceDataSetting.vue";
import { getInstanceData } from "@/api/LabInstanceApi";
import { ElMessage } from "element-plus";

const { isDark } = useDark();
const theme: EchartOptions["theme"] = computed(() => {
  return isDark.value ? "dark" : "default";
});

const lineChartRef = ref<HTMLDivElement | null>(null);

const props = defineProps({
  currentIndex: {
    type: Number,
    default: 0
  },
  settingLine: {
    type: Object
  },
  expInstId: {
    type: String
  },
  configId: {
    type: String,
    default: ""
  },
  expState: {
    type: Number
  },
  labExperimentData: {
    type: Object
  },
  hisFlag: {
    type: String,
    default: ""
  }
});
const emit = defineEmits([
  "update:settingLine",
  "delete-item",
  "data-confirm-click"
]);
const handleClickDelete = async () => {
  emit("delete-item", props.currentIndex);
};

const defaultPointsNum = 800;
const dataZoomStart = ref(0);
const dataZoomEnd = ref(100);
const initialDuration = props.settingLine.duration;

const timeWindow = ref(initialDuration);
const drawerSettingVisible = ref(false);
const chartOption = ref(JSON.parse(JSON.stringify(defaultChartOption)));
const settingRef = ref(defaultSetting);
settingRef.value = JSON.parse(JSON.stringify(props.settingLine));

const loading = ref(false);

const { setOptions, getInstance, resize } = useECharts(
  lineChartRef as Ref<HTMLDivElement>,
  {
    theme
  }
);

let timerUpdate = null;

//定时获取数据函数，出现在刚进入、实验状态更新、时间窗口更新
const updateTimer = newInterval => {
  //清除定时器
  clearInterval(timerUpdate);
  console.log("newInterval", newInterval);

  //如果定时器存在，并且实验状态为进行中，则重新设置定时器，获取数据
  if (timerUpdate && props.expState === 10) {
    timerUpdate = setInterval(async () => {
      await updateSeriesData(settingRef.value);
    }, newInterval);
  } else {
    return;
  }
};

const changeTimeWindow = (second: number) => {
  // for (const item of settingRef.value.optionY) {
  //   for (const sensor of item.sensors) {
  //     sensor.period = String(Math.ceil(second / defaultPointsNum));
  //   }
  // }

  //1分钟second=60
  //5分钟second=300
  //30分钟second=1800
  //60分钟second=3600
  //全部second=0

  //默认设置duration=second
  //timeWindow为选中时间框的值
  settingRef.value.duration = String(second);
  timeWindow.value = JSON.parse(JSON.stringify(settingRef.value.duration));

  //如果是全部，则做特殊处理
  console.log("changeTimeWindow", second);
  if (second === 0) {
    second = 60 * 60;

    //将second设置为实验进行时间
    try {
      //计算实验进行时间
      if (props.expState === 10) {
        second = Math.ceil(
          (new Date(chartOption.value.series[0].data[0][0]).getTime() -
            new Date(props.labExperimentData.startTime).getTime()) /
            1000
        );
      } else if (props.expState === 20) {
        second = Math.ceil(
          (new Date(props.labExperimentData.endTime).getTime() -
            new Date(props.labExperimentData.startTime).getTime()) /
            1000
        );
      }

      //如果second为0或者NaN，则设置为60*60*2
      if (isNaN(second) || second <= 60) {
        second = 60 * 60;
      }
    } catch (error) {
      second = 60 * 60;
    }

    settingRef.value.duration = String(second);
    timeWindow.value = 0;

    updateTimer(
      Math.ceil(settingRef.value.duration / defaultPointsNum + 1) * 1000
    );
  } else {
    updateTimer(
      Math.ceil(settingRef.value.duration / defaultPointsNum + 1) * 1000
    );
  }
};

const updateOption = () => {
  drawerSettingVisible.value = true;
};

const getSeriesData = async setting => {
  if (props.expState === 20 || props.expState === 10) {
    loading.value = true;
  }
  console.log("\n\n\n\n");

  console.log("getSeriesData");
  // debugger;
  const UnitList = {
    温度: "℃",
    压力: "MPa",
    开度: "%"
  };
  chartOption.value.yAxis[0].name = setting.optionY[0].mesure
    ? setting.optionY[0].mesure + UnitList[setting.optionY[0].mesure]
    : "Y1";

  chartOption.value.yAxis[1].name = setting.optionY[1].mesure
    ? setting.optionY[1].mesure + UnitList[setting.optionY[1].mesure]
    : "Y2";
  // chartOption.value.yAxis[1].name =
  //   setting.optionY[1].mesure + setting.optionY[1].unit || "Y2";
  chartOption.value.dataZoom[0].start = dataZoomStart.value;
  chartOption.value.dataZoom[0].end = dataZoomEnd.value;
  setOptions(chartOption.value as UtilsEChartsOption);

  let series = [];
  const legend = {
    data: []
  };
  let currentTime = "";

  if (props.expState === 20) {
    const date = new Date(props.labExperimentData.endTime);
    currentTime = formatDate(date);
  } else if (props.expState === 10) {
    const date = new Date();
    currentTime = formatDate(date);
  }

  // console.log("currentTime", currentTime);
  for (const [indexY, itemY] of setting.optionY.entries()) {
    for (const sensor of itemY.sensors) {
      legend.data.push(sensor.name);

      const second =
        Math.ceil(
          Math.min(
            new Date().getTime() -
              new Date(props.labExperimentData.startTime).getTime(),
            new Date(props.labExperimentData.endTime).getTime() -
              new Date(props.labExperimentData.startTime).getTime()
          )
        ) / 1000;

      try {
        // debugger;
        const tempData = await getInstanceData({
          expInstId: props.expInstId,
          devId: sensor.deviceId,
          startTime: currentTime,
          duration: setting.duration,
          period: String(Math.ceil(setting.duration / defaultPointsNum + 1))
        });
        console.log({
          expInstId: props.expInstId,
          devId: sensor.deviceId,
          startTime: currentTime,
          duration: setting.duration,
          period: String(Math.ceil(setting.duration / defaultPointsNum + 1))
        });
        if (!tempData.errorCode) {
          const regValue = (
            tempData.data as {
              dataPoints: { createTime: string; regValue: number }[];
            }
          ).dataPoints.map(obj => [obj.createTime, obj.regValue]);

          console.log("regValue", regValue);

          const targetIndex = series.findIndex(
            series => series.name === sensor.name
          );

          regValue.forEach(item => {
            const time_str = item[0];
            const time_obj = new Date(time_str);
            time_obj.setMilliseconds(0);
            item[0] = time_obj.toISOString().replace("T", " ");
          });

          if (regValue.length > 0) {
            chartOption.value.yAxis[0].max = null;
          }

          const newData = {
            name: sensor.name,
            data: regValue.length === 0 ? [[new Date()]] : regValue,
            type: "line",
            showSymbol: false,
            emphasis: {
              focus: "series",
              scale: true
            }
          };

          if (indexY == 1) {
            newData["yAxisIndex"] = 1;
          }
          series.push(newData);
        } else {
          console.error("请求错误", tempData.message);
          if (props.expState === 20 || props.expState === 10) {
            ElMessage.error("无法获取数据");
          }
          return;
        }

        // console.log(tempData);
      } catch (error) {
        console.error("捕获到错误：", error.message);
      }
    }
  }

  if (series.length === 0) {
    legend.data = ["无数据"];
    series = [
      {
        name: "无数据",
        type: "line",
        showSymbol: false,
        emphasis: {
          focus: "series",
          scale: true
        },
        data: [[new Date()]]
      }
    ];
  }

  chartOption.value = { ...chartOption.value, legend, series };
  setOptions(chartOption.value as UtilsEChartsOption);
  loading.value = false;
};

const formatDate = date => {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  const hours = String(date.getHours()).padStart(2, "0");
  const minutes = String(date.getMinutes()).padStart(2, "0");
  const seconds = String(date.getSeconds()).padStart(2, "0");

  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};

const updateSeriesData = async setting => {
  console.log("\n\nupdateSeriesData");
  if (
    setting.optionY[0].sensors.length === 0 &&
    setting.optionY[1].sensors.length === 0
  ) {
    return;
  }

  let series = [];

  try {
    series = JSON.parse(JSON.stringify(chartOption.value.series));
  } catch (error) {
    return;
  }

  // const currentTime = new Date();
  const date = new Date();
  date.setSeconds(date.getSeconds() - 1);
  const currentTime = formatDate(date);
  console.log("currentTimeUpdate", currentTime);

  for (const itemY of setting.optionY) {
    for (const sensor of itemY.sensors) {
      const targetIndex = series.findIndex(
        series => series.name === sensor.name
      );
      try {
        const tempData = await getInstanceData({
          expInstId: props.expInstId,
          devId: sensor.deviceId,
          startTime: currentTime,
          duration: String(Math.ceil(setting.duration / defaultPointsNum + 1)),
          period: String(Math.ceil(setting.duration / defaultPointsNum + 1))
        });
        console.log({
          expInstId: props.expInstId,
          devId: sensor.deviceId,
          startTime: currentTime,
          duration: String(Math.ceil(setting.duration / defaultPointsNum + 1)),
          period: String(Math.ceil(setting.duration / defaultPointsNum + 1))
        });
        if (!tempData.errorCode) {
          if (tempData.data.dataPoints.length > 0) {
            console.log(
              "传回",
              sensor.name,
              tempData.data.dataPoints[0].createTime
            );
          }
          const regValue = (
            tempData.data as {
              dataPoints: { createTime: string; regValue: number }[];
            }
          ).dataPoints.map(obj => [currentTime, obj.regValue]);

          console.log(sensor.name, regValue[0]);
          console.log(series[targetIndex].data.length);
          regValue.forEach(item => {
            series[targetIndex].data.unshift(item);
            const startTime = new Date(
              new Date(currentTime).getTime() - (setting.duration + 1) * 1000
            );
            //截取在规定时间段内的值
            series[targetIndex].data = series[targetIndex].data.filter(item => {
              const time = new Date(item[0]);
              return time >= startTime && time <= new Date(currentTime);
            });

            // 去重;
            // series[targetIndex].data = series[targetIndex].data.filter(
            //   (item, index) => {
            //     return (
            //       series[targetIndex].data.findIndex(
            //         arr => JSON.stringify(arr) === JSON.stringify(item)
            //       ) === index
            //     );
            //   }
            // );

            //默认800个点，如果比800多则删除第一个
            // setting.duration /
            //   Math.ceil(setting.duration / defaultPointsNum + 1);
            if (series[targetIndex].data.length > 80)
              series[targetIndex].data.pop();

            //时间取整
            series[targetIndex].data = series[targetIndex].data.map(item => {
              const time = new Date(item[0]);
              time.setMilliseconds(0);

              return [time.toISOString(), item[1]];
            });
          });
        } else {
          ElMessage.error(`更新数据失败：${tempData.message}`);
          console.log(tempData.message);
          throw new Error("发生错误了！");
        }
      } catch (error) {
        console.log(error);
        console.error("捕获到错误：", error.message);
        return;
      }
    }
  }

  chartOption.value.yAxis[0].max = null;

  chartOption.value = { ...chartOption.value, series };

  setOptions(chartOption.value as UtilsEChartsOption);
};

const dataConfirmClick = () => {
  emit("data-confirm-click");
};

onMounted(() => {
  console.log("onMounted", props.expState);
  //切换时间刻度
  if (
    initialDuration != 60 &&
    initialDuration != 5 * 60 &&
    initialDuration != 30 * 60 &&
    initialDuration != 60 * 60
  ) {
    timeWindow.value = 0;
  }

  //是否结束，结束则切换历史记录模板
  if (props.expState === 20) {
    console.log("本实验已结束");
    chartOption.value = JSON.parse(JSON.stringify(hisdataChartOption));
    // console.log(chartOption.value);
    settingRef.value.duration = String(
      Math.ceil(
        (new Date(props.labExperimentData.endTime).getTime() -
          new Date(props.labExperimentData.startTime).getTime()) /
          1000
      )
    );
    changeTimeWindow(0);
    //存疑！！
  }
  if (props.hisFlag == "1") {
    changeTimeWindow(0);
  }

  getInstance()!.on("datazoom", event => {
    if (event.batch) {
      // 在图表内使用鼠标滚轮缩放
      dataZoomStart.value = event.batch[0].start;
      dataZoomEnd.value = event.batch[0].end;
    } else {
      dataZoomStart.value = event.start;
      dataZoomEnd.value = event.end;
    }
  });

  chartOption.value.dataZoom[0].start = dataZoomStart.value;
  chartOption.value.dataZoom[0].end = dataZoomEnd.value;
  chartOption.value.yAxis[0].name =
    settingRef.value.optionY[0].mesure + settingRef.value.optionY[0].unit;
  chartOption.value.yAxis[1].name =
    settingRef.value.optionY[1].mesure + settingRef.value.optionY[1].unit;
  setOptions(chartOption.value as UtilsEChartsOption);

  //判断实验状态
  //20为结束，10为进行中
  if (props.expState === 20) {
    console.log("已结束，获取数据");
    getSeriesData(settingRef.value);
  }
  if (props.expState === 10) {
    getSeriesData(settingRef.value);

    timerUpdate = setInterval(async () => {
      await updateSeriesData(settingRef.value);
    }, Math.ceil(props.settingLine.duration / defaultPointsNum + 1) * 1000);
  }
  updateTimer(
    Math.ceil(props.settingLine.duration / defaultPointsNum + 1) * 1000
  );
});

onUnmounted(() => {
  if (timerUpdate) {
    // console.log("clearInterval");
    clearInterval(timerUpdate);
    timerUpdate = null;
  }
});

watch(
  () => [dataZoomStart.value, dataZoomEnd.value],
  ([valStart, valEnd]) => {
    chartOption.value.dataZoom[0].start = valStart;
    chartOption.value.dataZoom[0].end = valEnd;
  }
);

watch(
  () => settingRef.value.duration,
  val => {
    // console.log("duration变化，更新数据", val);
    emit("update:settingLine", JSON.parse(JSON.stringify(settingRef.value)));
    emit("data-confirm-click");
    getSeriesData(settingRef.value);
  }
);

watch(settingRef, val => {
  // console.log("setting值变化，更新数据", val);
  emit("update:settingLine", JSON.parse(JSON.stringify(settingRef.value)));
  emit("data-confirm-click");
  getSeriesData(settingRef.value);
});

watch(
  () => props.expState,
  val => {
    console.log("watch", props.expState);
    //监控实验状态
    //如果10为进行中，则开始定时更新数据
    if (val === 10) {
      console.log("进行中");

      getSeriesData(settingRef.value);
      // router.go(0);
      timerUpdate = setInterval(async () => {
        await updateSeriesData(settingRef.value);
      }, Math.ceil(props.settingLine.duration / defaultPointsNum + 1) * 1000);
    }

    // if (val === 20) {
    //   console.log("已结束");
    //   chartOption.value = JSON.parse(JSON.stringify(hisdataChartOption));
    //   console.log(chartOption.value);
    //   settingRef.value.duration = String(
    //     Math.ceil(
    //       (new Date(props.labExperimentData.endTime).getTime() -
    //         new Date(props.labExperimentData.startTime).getTime()) /
    //         1000
    //     )
    //   );
    //   //存疑！！
    // }
    // getInstance()!.on("datazoom", event => {
    //   if (event.batch) {
    //     // 在图表内使用鼠标滚轮缩放
    //     dataZoomStart.value = event.batch[0].start;
    //     dataZoomEnd.value = event.batch[0].end;
    //   } else {
    //     dataZoomStart.value = event.start;
    //     dataZoomEnd.value = event.end;
    //   }
    // });

    // chartOption.value.dataZoom[0].start = dataZoomStart.value;
    // chartOption.value.dataZoom[0].end = dataZoomEnd.value;

    // setOptions(chartOption.value as UtilsEChartsOption);

    // //判断实验状态
    // //20为结束，10为进行中
    // if (val === 20) {
    //   getSeriesData(settingRef.value);
    // }
    // if (val === 10) {
    //   getSeriesData(settingRef.value);

    //   timerUpdate = setInterval(async () => {
    //     await updateSeriesData(settingRef.value);
    //   }, Math.ceil(props.settingLine.duration / defaultPointsNum) * 1000);
    // }

    // updateTimer(
    //   Math.ceil(props.settingLine.duration / defaultPointsNum) * 1000
    // );
  }
);

watch(
  () => useAppStoreHook().getSidebarStatus,
  () => {
    delay(600).then(() => resize());
  }
);
useResizeObserver(lineChartRef, () => {
  delay(600).then(() => resize());
});
</script>

<template>
  <div>
    <!-- {{ settingRef.duration }}
    {{ timeWindow }}
    {{ hisFlag }} -->
    <div
      style="
        display: flex;
        justify-content: center;
        align-items: center;
        margin-bottom: 10px;
      "
    >
      <el-text style="font-weight: bold; font-size: 18px">{{
        settingRef.name
      }}</el-text>
    </div>
    <div style="display: flex; margin-bottom: 30px; align-items: center">
      <el-button
        type="primary"
        :disabled="expState == 20 || expState == 10 ? true : false"
        @click="updateOption()"
        >配置</el-button
      >
      <el-radio-group style="margin-left: 30px" v-model="timeWindow">
        <el-radio-button
          v-if="expState != 20 && hisFlag == ''"
          :label="String(1 * 60)"
          @click="changeTimeWindow(1 * 60)"
          >1分钟
        </el-radio-button>
        <el-radio-button
          v-if="expState != 20 && hisFlag == ''"
          :label="String(5 * 60)"
          @click="changeTimeWindow(5 * 60)"
          >5分钟
        </el-radio-button>
        <el-radio-button
          v-if="expState != 20 && hisFlag == ''"
          :label="String(30 * 60)"
          @click="changeTimeWindow(30 * 60)"
          >30分钟
        </el-radio-button>
        <el-radio-button
          v-if="expState != 20 && hisFlag == ''"
          :label="String(60 * 60)"
          @click="changeTimeWindow(60 * 60)"
          >60分钟
        </el-radio-button>
        <el-radio-button :label="String(0)" @click="changeTimeWindow(0)"
          >全部
        </el-radio-button>
      </el-radio-group>

      <div style="display: flex; margin-left: auto">
        <el-button
          type="info"
          :disabled="expState == 20 || expState == 10 ? true : false"
          text
          bg
          @click="handleClickDelete"
        >
          <IconifyIconOnline
            icon="material-symbols:delete-outline"
            style="margin-right: 2px; color: #b2b2b2"
          />
          删除
        </el-button>
      </div>
    </div>
    <!-- {{ loading }} -->

    <div v-loading="loading" element-loading-text="加载中...">
      <div ref="lineChartRef" style="width: 100%; height: 40vh" />
    </div>
    <!-- {{ settingRef }} -->
    <InstanceDataSetting
      @data-confirm-click="dataConfirmClick"
      :configId="configId"
      v-model:visible="drawerSettingVisible"
      v-model:setting="settingRef"
      :currentIndex="currentIndex"
      :defaultPointsNum="defaultPointsNum"
    />
  </div>
</template>
